package org.threads.circlebuffer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.UUID;

/**
 * Thread for generating messages and adding them
 * into CircleBuffer object. Messages are generated UUID
 * numbers.
 *
 * @see org.threads.circlebuffer.CircleBuffer
 */
public class GeneratorThread extends Thread {

    private static final Logger LOGGER = LoggerFactory.getLogger(GeneratorThread.class);

    private CircleBuffer buffer;

    /**
     * Creates a GeneratorThread object with shared CircleBuffer.
     *
     * @param buffer circle buffer
     */
    public GeneratorThread(CircleBuffer buffer) {
        setBuffer(buffer);
    }

    /**
     * Entry point, used for testing.
     *
     * @param args
     */
    public static void main(String[] args) throws InterruptedException {

        final long testingTime = 2000;
        final int cbGenCount = 5;
        final int cbObtCount = 3;
        final int cbSize = 50;

        final CircleBuffer cb = new CircleBuffer(cbSize);

        for (int i = 0; i < cbObtCount; i++) {
            Thread t = new ObtainThread(cb);
            t.setDaemon(true);
            t.start();
        }

        for (int i = 0; i < cbGenCount; i++) {
            Thread t = new GeneratorThread(cb);
            t.setDaemon(true);
            t.start();
        }

        Thread.sleep(testingTime);

    }

    @Override
    public void run() {

        long threadId = Thread.currentThread().getId();

        while (true) {

            String message = "Thread #" + threadId + " has GENERATED: "
                    + UUID.randomUUID().toString();

            try {

                buffer.add(message);
                LOGGER.info(message);

            } catch (InterruptedException e) {
                LOGGER.error(e.toString());
            }
        }
    }

    /**
     * Used for internal setting the buffer. Don't use straight initialization.
     *
     * @param buffer circle buffer
     */
    private void setBuffer(CircleBuffer buffer) {

        if (buffer == null) {
            throw new IllegalArgumentException(CircleBuffer.CIRCLE_BUFFER_NULL_EX);
        }
        this.buffer = buffer;
    }

}
